import re
import holidays
import numpy as np
import phonenumbers
from datetime import datetime, timedelta
from feature_conf.config import GenericConfigConstant


def fea_div(a, b):
    """
    Returns four significant figures for the ratio of two data
    Args:
        a: molecule
        b: denominator

    Returns:
        if b == 0, return None, else return round(a / b, 4)
    """
    return -99 if b == 0 else round(a / b, 4)


def get_data_format(value, sub_type='0'):
    """
    对于金额类的值，sub_type=0,当为null的时候，返回0，对于标准差类的，当sub_type='1',当值为null的时候返回-99
    """
    if sub_type == '0':
        if np.isnan(value):
            return 0
        else:
            return value
    elif sub_type == '1':
        if np.isnan(value):
            return -99
        else:
            return value


def format_personal_phone_num(phone_num, country_id):
    """
    Standardize personal phone numbers and exclude public numbers
    Args:
        phone_num: phone number
        country_id: country id

    Returns:
        Formatted phone number
    """
    if country_id not in GenericConfigConstant.COUNTRY_ID:
        raise ValueError("country id not in list, Please input correct country id")

    format_len = GenericConfigConstant.COUNTRY_PHONE_LEN[country_id]
    country_code = GenericConfigConstant.COUNTRY_CODE[country_id]
    phone_num = str(phone_num).replace(' ', '')
    phone_num = phone_num.replace(country_code, '')
    phone_num = re.sub(r'[^0-9]', '', phone_num)
    if len(phone_num) == format_len:
        return phone_num
    else:
        return None


def format_public_phone_num(phone_num, country_id):
    """
    Standardize public phone numbers
    Args:
        phone_num: phone number
        country_id: country id

    Returns:
        Formatted phone number
    """
    pass


def divide(a, b):
    if b == 0:
        return np.nan
    return a / b


def phone_normalize(phone, country_id):
    """
    :param phone:
    :param country_id: 国家地区代码 ISO标准 .e.g.MX、CL,需大写
    :return:
    """
    phone = re.sub(r'[*\#\-()\n\t \u202A\u202C]+', '', str(phone)).lower()
    phone = phone[:]
    length = len(phone)
    # 清洗+00593964132978该类手机号
    try:
        if phone[0] == '+':
            phone = '+' + phone.replace('+', '').lstrip('0')
            length = len(phone) - 1
        else:
            phone = phone.lstrip('0')
            length = len(phone)
    except Exception:
        pass
    # 初始化
    is_valid, country_code, national_phone = 0, '', phone.lstrip('+')

    # 若手机号长度小于7（最短手机号），则返回
    if length < 7:
        return str(national_phone)

    try:
        if phone.startswith('+'):
            parse_info = phonenumbers.parse(phone)
        else:
            parse_info = phonenumbers.parse(phone, country_id)

        is_valid = 1 if phonenumbers.is_valid_number(parse_info) else 0
        if is_valid:
            national_phone = parse_info.national_number
            return str(national_phone)
    except Exception:
        pass

    return str(national_phone)


def sp_string_replace(x):
    res = x.replace('á', 'a').replace('é', 'e').replace('í', 'i').replace('ó', 'o').replace('ú', 'u').replace('ü',
                                                                                                              'u').replace(
        '¡', '')
    return res


def get_holidays(country_id, self_date):
    country_id = country_id.upper()
    self_date = self_date[:10]
    country_holidays = holidays.country_holidays(country_id)
    is_holidays = self_date in country_holidays
    if is_holidays:
        return 1
    else:
        return 0


def get_workday(self_date):
    weekday = datetime.strptime(str(self_date), "%Y-%m-%d %H:%M:%S").weekday()
    if weekday < 5:
        return 1
    else:
        return 0


def get_email_type(email):
    if '@hotmail.com' in email:
        return 1
    elif '@gmail.com' in email:
        return 2
    else:
        return 0


def fea_div_v2(a, b):
    """
    Returns four significant figures for the ratio of two data
    Args:
        a: molecule
        b: denominator

    Returns:
        if b == 0, return None, else return round(a / b, 4)
    """
    return -999 if b == 0 else round(a / b, 4)


def get_days_inter(end_time, start_time):
    """
    获取日期间隔
    """
    from datetime import datetime
    end_time = datetime.strptime(end_time, "%Y-%m-%d %H:%M:%S")
    start_time = datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S")
    interval = end_time - start_time
    return int(interval.days)


def find_max_consecutive(data):
    if not data:
        return {}

    max_counts = {}
    max_sequences = {}
    current_value = data[0]
    current_count = 1
    start_index = 0

    for i in range(1, len(data)):
        if data[i] == current_value:
            current_count += 1
        else:
            # 更新最大连续次数和索引
            if current_count > max_counts.get(current_value, 0):
                max_counts[current_value] = current_count
                max_sequences[current_value] = (start_index, i-1)
            elif current_count == max_counts.get(current_value, 0):
                # 如果次数相同，选择索引最大的
                if max_sequences[current_value][1] < i-1:
                    max_sequences[current_value] = (start_index, i-1)
            current_value = data[i]
            current_count = 1
            start_index = i

    # 处理数组最后一个元素
    if current_count > max_counts.get(current_value, 0):
        max_counts[current_value] = current_count
        max_sequences[current_value] = (start_index, len(data)-1)
    elif current_count == max_counts.get(current_value, 0):
        # 如果次数相同，选择索引最大的
        if max_sequences[current_value][1] < len(data)-1:
            max_sequences[current_value] = (start_index, len(data)-1)

    return max_sequences


def get_current_time_type(_time):
    """
    获取时间类型，早上 下午 晚上 凌晨
    """
    import pandas as pd
    time_type = pd.to_datetime(_time).hour
    if 12 >= time_type >= 6:
        return 1
    elif 18 >= time_type >= 13:
        return 2
    elif 23 >= time_type >= 19:
        return 3
    else:
        return 4


def is_decimal(string):
    pattern = r'^-?\d+\.\d+$'
    return bool(re.match(pattern, string))